package com.chenzhou.qx.checklibrary;

import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * Hook PackageManager
 *
 * @author tk
 * @date 2021/1/28
 */
public class HookPackageManager {

    private static final String TAG = "HookPackageManager";

    private static List<String> hookMethodNames = new ArrayList<String>() {{
        add("getInstalledPackages");
        add("queryIntentActivities");
        add("getInstalledApplications");
    }};

    public static void setHookList(List<String> list) {
        hookMethodNames = list;
    }

    public static void addHooks(String... hookNames) {
        if (hookNames != null && hookNames.length > 0) {
            for (int i = 0; i < hookNames.length; i++) {
                if (!hookMethodNames.contains(hookNames[i])) {
                    hookMethodNames.add(hookNames[i]);
                }
            }
        }
    }

    public static void hookIPackageManager() {
        try {
            Field sPackageManagerField = Class.forName("android.app.ActivityThread").getDeclaredField("sPackageManager");
            sPackageManagerField.setAccessible(true);
            final Object obj = sPackageManagerField.get(null);
            Log.d(TAG, "sPackageManagerObj=" + obj);

            Class ipm = Class.forName("android.content.pm.IPackageManager");
            Object proxyObj = Proxy.newProxyInstance(ipm.getClassLoader(), new Class[]{ipm}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    if (hookMethodNames.contains(method.getName())) {
                        Log.e(TAG, Log.getStackTraceString(new Throwable()));
                    }

                    return method.invoke(obj, args);
                }
            });

            sPackageManagerField.set(null, proxyObj);

            Log.d(TAG, "hook packagemanager ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
